package stardust.core.support;


/**
 * 安全的序列生成器
 * <p>
 * 提供可靠的序列数字。 确保同一实例类不会产生相同的序列号。
 * <p/>
 * @author ChenChang
 */
public class Sequence
{

  /**
   * 序列索引
   */
  private long index;

  /**
   * 偏移量
   */
  private long offset;

  /**
   * 增量
   */
  private long inc;

  /**
   * 获取一个默认的序列
   */
  public Sequence()
  {
    this(0, 1);
  }

  /**
   * 通过偏移量获取序列
   * <p/>
   * @param offset
   */
  public Sequence(long offset)
  {
    this(offset, 1);
  }

  /**
   * 通过偏移量和增量获取序列
   * <p/>
   * @param offset
param inc
   */
  public Sequence(long offset, long inc)
  {
    if (inc == 0)
    {
      throw new IllegalArgumentException("序列的增量不能等于或小于零。");
    }

    this.index = 0;
    this.offset = offset;
    this.inc = inc;
  }

  /**
   * 序列当前值
   * <p/>
   * @return
   */
  public long current()
  {
    return this.index + this.offset;
  }

  /**
   * 序列自增并返回自增后的值
   * <p/>
   * @return
   */
  public long next()
  {
    if (this.index + this.inc + this.offset >= Long.MIN_VALUE && this.index + this.inc + this.offset <= Long.MAX_VALUE)
    {
      return (this.index += this.inc) + this.offset;
    }
    else
    {
      throw new IllegalStateException("序列索引已经达到极限值。");
    }
  }

  /**
   * 序列自减并返回自减后的值
   * <p/>
   * @return
   */
  public long back()
  {
    if (this.index - this.inc + this.offset >= Long.MIN_VALUE && this.index - this.inc + this.offset <= Long.MAX_VALUE)
    {
      return (this.index -= this.inc) + this.offset;
    }
    else
    {
      throw new IllegalStateException("序列索引已经达到极限值。");
    }
  }

}
